
package com.kaciula.letsdoit.service;

import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.kaciula.letsdoit.db.WastesDbAdapter;
import com.kaciula.letsdoit.ui.Constants;
import com.kaciula.letsdoit.ui.MyApplication;
import com.kaciula.letsdoit.ui.PreferenceHelper;
import com.kaciula.utils.StorageHelper;
import com.kaciula.utils.WebService;

import org.apache.commons.codec.binary.Base64;

import android.content.Context;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.util.Log;

import java.io.ByteArrayOutputStream;
import java.lang.reflect.Type;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

public class LdirWebService {

    private Context mCtx;

    private WebService mWebService;

    private WastesDbAdapter mDbHelper;

    private PreferenceHelper mPrefHelper;

    public static final String WEB_SERVICE_BASE_NAME = "http://ldir-mobile.gtstelecom.ro/";

    public static final String WASTE_ADDRESS = "LetsDoItWS/WastesService.svc/v1/waste/json";

    public static final String IMAGE_ADDRESS = "LetsDoItWS/WastesService.svc/v1/images/%s";

    public static final String VALIDATE_ADDRESS = "LetsDoItWS/AuthService.svc/v1/validate/%s(%s)/json";

    public static final String USER_SALT_ADDRESS = "LetsDoItWS/AuthService.svc/v1/usersalt/%s/json";

    private static final String TAG = "LdirWebService";

    private static final String MD5_ALGORITHM = "MD5";

    private static final String CONTENT_TYPE_JSON = "application/json";

    private static final String CONTENT_TYPE_STREAM = "application/octet-stream";

    public LdirWebService(Context ctx) {
        mCtx = ctx;

        /*
         * Instantiate the Web Service with the URL of the web service that you
         * must pass
         */
        mWebService = new WebService(WEB_SERVICE_BASE_NAME);

        mDbHelper = new WastesDbAdapter(mCtx);

        mPrefHelper = ((MyApplication)mCtx.getApplicationContext()).getPrefHelper();
    }

    public String getUserSalt(String username) {
        // Pass the parameters if needed , if not then pass dummy one as follows
        Map<String, String> params = new HashMap<String, String>();
        params.put("dummy", "");

        String method = String.format(USER_SALT_ADDRESS, username);

        /*
         * Get JSON response from server
         */
        String response = mWebService.get(method, params);

        Type stringType = new TypeToken<String>() {
        }.getType();
        String salt = new Gson().fromJson(response, stringType);

        return salt;
    }

    public boolean validateUser(String username, String md5pass) {
        // Pass the parameters if needed , if not then pass dummy one as follows
        Map<String, String> params = new HashMap<String, String>();
        params.put("dummy", "");

        String method = String.format(VALIDATE_ADDRESS, username, md5pass);

        /*
         * Get JSON response from server
         */
        String response = mWebService.get(method, params);

        Type booleanType = new TypeToken<Boolean>() {
        }.getType();
        Boolean isValid = new Gson().fromJson(response, booleanType);

        return isValid;
    }

    public void uploadWaste(long id, String username, String md5Pass, boolean isTest) {
        mDbHelper.open();
        WasteRequest waste = new WasteRequest();
        Cursor wasteCursor = mDbHelper.fetchWaste(id);

        if (wasteCursor.moveToFirst()) {
            double vald1, vald2;
            String text;
            int val;

            text = wasteCursor.getString(wasteCursor
                    .getColumnIndexOrThrow(WastesDbAdapter.KEY_ROWID));
            waste.setID(text);

            vald1 = wasteCursor.getDouble(wasteCursor
                    .getColumnIndexOrThrow(WastesDbAdapter.KEY_LAT));
            vald2 = wasteCursor.getDouble(wasteCursor
                    .getColumnIndexOrThrow(WastesDbAdapter.KEY_LONG));
            waste.setLocation(vald1, vald2);

            val = wasteCursor.getInt(wasteCursor.getColumnIndexOrThrow(WastesDbAdapter.KEY_LENGTH));
            waste.setLength(val);

            val = wasteCursor
                    .getInt(wasteCursor.getColumnIndexOrThrow(WastesDbAdapter.KEY_BREADTH));
            waste.setWidth(val);

            val = wasteCursor.getInt(wasteCursor.getColumnIndexOrThrow(WastesDbAdapter.KEY_HEIGHT));
            waste.setHeight(val);

            val = wasteCursor.getInt(wasteCursor
                    .getColumnIndexOrThrow(WastesDbAdapter.KEY_DISPERSED));
            waste.setIsDispersed(val != 0);

            val = wasteCursor.getInt(wasteCursor
                    .getColumnIndexOrThrow(WastesDbAdapter.KEY_EQUIVALENT));
            waste.setBagEq(val);

            text = wasteCursor.getString(wasteCursor
                    .getColumnIndexOrThrow(WastesDbAdapter.KEY_DESCRIPTION));
            waste.setDescription(text);

            val = wasteCursor.getInt(wasteCursor
                    .getColumnIndexOrThrow(WastesDbAdapter.KEY_COMPOSITION_NOT_RECYCLABLE));
            waste.setPercentageOrganic(val);

            val = wasteCursor.getInt(wasteCursor
                    .getColumnIndexOrThrow(WastesDbAdapter.KEY_COMPOSITION_GLASS));
            waste.setPercentageGlass(val);

            val = wasteCursor.getInt(wasteCursor
                    .getColumnIndexOrThrow(WastesDbAdapter.KEY_COMPOSITION_METAL));
            waste.setPercentageMetal(val);

            val = wasteCursor.getInt(wasteCursor
                    .getColumnIndexOrThrow(WastesDbAdapter.KEY_COMPOSITION_PLASTIC));
            waste.setPercentagePlastic(val);

            val = wasteCursor.getInt(wasteCursor
                    .getColumnIndexOrThrow(WastesDbAdapter.KEY_COMPOSITION_PAPER));
            waste.setPercentageCarton(val);

            val = wasteCursor.getInt(wasteCursor
                    .getColumnIndexOrThrow(WastesDbAdapter.KEY_COMPOSITION_TIRE));
            waste.setPercentageRubber(val);

            val = wasteCursor.getInt(wasteCursor
                    .getColumnIndexOrThrow(WastesDbAdapter.KEY_COMPOSITION_BIG_VOLUME));
            waste.setPercentageVolume(val);

            val = wasteCursor.getInt(wasteCursor
                    .getColumnIndexOrThrow(WastesDbAdapter.KEY_COMPOSITION_CONSTRUCTION_MATERIAL));
            waste.setPercentageRawMatterials(val);

            waste.setPostingDateTime(new Date());
            waste.setIsTest(isTest);
        }

        wasteCursor.close();
        mDbHelper.close();

        String data = null;

        data = new Gson().toJson(waste);
        Log.d(TAG, "data=[" + data + "]");

        String auth = username + ":" + md5Pass;
        auth = new String(Base64.encodeBase64(auth.getBytes()));

        /*
         * Get JSON response from server
         */
        String response = mWebService.post(WASTE_ADDRESS, data, CONTENT_TYPE_JSON,
                CONTENT_TYPE_JSON, auth);
        Log.d(TAG, "response=[" + response + "]");

        Type responseType = new TypeToken<WasteResponse>() {
        }.getType();
        WasteResponse wasteResponse = new Gson().fromJson(response, responseType);

        if (wasteResponse.isSucces()) {
            String wasteServerId = wasteResponse.getServerID();
            uploadImage(id, 1, wasteServerId, auth);
            uploadImage(id, 2, wasteServerId, auth);
        }
    }

    public void uploadImage(long id, int no, String wasteServerId, String auth) {
        String path = mPrefHelper.getPicPath(id, no);
        Bitmap bitmap = StorageHelper.getBitmap(path, Constants.SAMPLE_SIZE);
        ByteArrayOutputStream out = new ByteArrayOutputStream(10240);

        if (bitmap != null) {
            bitmap.compress(CompressFormat.JPEG, 100, out);

            String method = String.format(IMAGE_ADDRESS, wasteServerId);
            String response = mWebService.post(method, out, CONTENT_TYPE_STREAM, CONTENT_TYPE_JSON,
                    auth);
            Log.d(TAG, "response=" + response);
        }
    }

    public void uploadAllWastes(String username, String md5Pass, boolean isTest) {
        long id;

        mDbHelper.open();
        Cursor wastesCursor = mDbHelper.fetchAllWastes();

        wastesCursor.moveToFirst();
        do {
            id = wastesCursor
                    .getLong(wastesCursor.getColumnIndexOrThrow(WastesDbAdapter.KEY_ROWID));
            uploadWaste(id, username, md5Pass, isTest);
        } while (wastesCursor.moveToNext());

        wastesCursor.close();
        mDbHelper.close();
    }

    public String generateMd5Pass(String password, String salt) {
        String pass = password + salt;
        MessageDigest msgDigest = null;

        try {
            msgDigest = MessageDigest.getInstance(MD5_ALGORITHM);
        } catch (NoSuchAlgorithmException e) {
            throw new AssertionError(e.getMessage());
        }

        byte[] bytes = msgDigest.digest(pass.getBytes());

        StringBuffer md5Pass = new StringBuffer();
        for (int i = 0; i < bytes.length; i++) {
            String hex = Integer.toHexString(0xFF & bytes[i]);
            if (hex.length() == 1) {
                md5Pass.append('0');
            }
            md5Pass.append(hex);
        }

        return md5Pass.toString();
    }
}
